------------------操作系统------------------
用户态和内核态
指处理器运行在不同权限级别的两种模式。这两种模式的设计目的是为了提高系统的安全性,并且防止用户程序错误地影响到整个系统的稳定性和数据的安全性。
用户态(User Mode)
用户态是指普通应用程序运行时所在的模式。在这种模式下,应用程序只能访问受限制的系统资源和服务。用户态程序不能直接访问硬件或执行某些特权指令,这样可以防止由于程序错误或恶意行为而导致系统崩溃或数据损坏。
在用户态下运行的应用程序包括但不限于:
- 文档编辑器
- 游戏
- 浏览器
- 办公软件
- 大部分用户级服务
内核态(Kernel Mode)
内核态是指操作系统内核运行时所在的模式。在内核态下,程序拥有完全的系统访问权限,可以执行任何指令,直接访问硬件资源。这种模式下的代码通常是经过严格审查的,因为任何错误都可能导致系统不稳定甚至崩溃。
在内核态下运行的组件包括:
- 文件系统驱动
- 设备驱动
- 网络协议栈
- 进程调度器
- 内存管理模块
用户态和内核态之间的转换
用户态下的应用程序需要调用操作系统提供的系统调用(System Call)来请求内核提供的服务,例如读写文件、分配内存、创建进程等。当应用程序发起一个系统调用时,CPU会从用户态切换到内核态,操作系统内核处理完请求后再从内核态切换回用户态。这种转换涉及到:
- 保护上下文:保存用户态的寄存器状态和程序计数器。
- 执行系统调用处理程序:操作系统内核中的代码负责处理系统调用。
- 恢复上下文:完成系统调用后,恢复用户态的寄存器状态和程序计数器。
进程的调度算法
调度算法 | 描述 | 优点 | 缺点 |
---|---|---|---|
先来先服务(First-Come, First-Served, FCFS) | 按照进程到达的先后顺序进行调度 | 实现简单,易于理解 | 可能导致长进程饿死短进程(长作业优先),响应时间较长 |
短作业优先(Shortest Job First, SJF) | 总是选择预计执行时间最短的进程来执行 | 可以最小化平均等待时间 | 需要知道进程的确切执行时间,实现复杂,且可能不公平对待长进程 |
最短剩余时间优先(Shortest Remaining Time First, SRTF) | 总是选择剩余执行时间最短的进程来执行 | 可以动态调整,更好地适应实际情况 | 需要实时更新剩余时间,实现较为复杂 |
时间片轮转(Round Robin, RR) | 给每个就绪队列中的进程分配一个固定的时间片(时间量子),并在时间片结束后强制切换到下一个进程 | 简单公平,适用于交互式系统 | 时间片的选择至关重要,否则可能会影响响应时间和吞吐量 |
优先级调度(Priority Scheduling) | 根据进程的优先级来调度,优先级高的进程优先执行 | 可以根据进程的重要性灵活调度 | 可能造成饥饿(starvation),即低优先级的进程永远得不到执行的机会 |
……还有很多,不列举了
进程间的通信方式
进程间通信(IPC)主要包括以下几种方式:
- 管道(Pipe)是最古老的进程间通信机制之一,所有的 UNIX 系统都支持这种机制。管道实质上是内核维护的一块内存缓冲区。Linux 系统中通过
pipe()
函数创建管道,这会生成两个文件描述符,分别对应管道的读端和写端。无名管道仅限于具有亲缘关系的进程间通信。 - 命名管道(FIFO) 命名管道(Named Pipe 或 FIFO 文件)克服了无名管道只能用于亲缘进程通信的限制。命名管道提供了一个路径名与之关联,作为文件系统中的一个 FIFO 文件存在。任何能够访问该路径的进程,即便与创建该 FIFO 的进程无关,也可以通过该 FIFO 进行通信。
- 信号 信号是进程间通信的另一种古老方式,作为一种异步通知机制,它可以在一个进程中产生中断,使进程能够响应某些事件。信号可以看作是软件层次上的中断机制,用于处理突发事件。
- 消息队列 消息队列是一个链表结构,其中包含具有特定格式和优先级的消息。具有写权限的进程可以按规则向消息队列中添加消息,而具有读权限的进程可以从队列中读取消息。消息队列是随内核持续存在的。
- 共享内存 共享内存允许多个进程共享同一块物理内存区域。这种机制允许进程直接在共享内存中进行数据交换,不需要内核的干预,因此速度较快。
- 内存映射 内存映射技术将磁盘文件的数据映射到内存,用户可以通过修改内存中的内容来间接修改磁盘文件。
- 信号量 信号用于解决进程或线程间的同步问题。对信号量的操作包括 P 操作(减 1)和 V 操作(加 1),用于控制进程或线程的互斥访问。
- Socket Socket 是网络中不同主机上应用程序之间进行双向通信的端点的抽象。它为应用层提供了使用网络协议进行数据交换的机制,主要用于网络中不同主机上的进程间通信。
什么是软中断、什么是硬中断?
中断类型 | 描述 | 特点 | 例子 |
---|---|---|---|
硬中断 | 由硬件设备引发的中断信号 | 外部来源:由外部硬件设备引发。 硬件触发:通常由设备通过 IRQ 线向 CPU 发送中断信号。 实时性:通常要求立即响应。 硬件驱动程序处理:中断处理程序通常由硬件驱动程序编写。 | 键盘中断:按下键盘按键。 网络中断:网络适配器接收到数据包。 定时器中断:定时器硬件定时发送中断信号。 |
软中断 | 由软件指令或内核代码触发的中断信号 | 内部来源:由软件指令或内核代码触发。 软件触发:通过特定的指令或函数调用触发。 灵活性:可以根据需要随时触发。 内核处理:通常由内核中的中断处理程序处理。 | 系统调用:应用程序调用系统服务。 时间片到期:时间片结束时触发。 异常处理:如页错误、除零错误等。 |
什么是分段、什么是分页?
特点 | 分段(Segmentation) | 分页(Paging) |
---|---|---|
逻辑划分 | 将逻辑地址空间划分为多个逻辑段,每个段代表程序的一部分。 | 将逻辑地址空间划分为固定大小的页面。 |
大小 | 段的大小可以是动态变化的,每个段可以有不同的大小。 | 页面的大小是固定的,通常是 4KB 或更大。 |
映射 | 段可以映射到物理内存中的连续或非连续区域。 | 页面映射到物理内存中的连续或非连续区域。 |
保护 | 每个段可以单独保护和管理,有利于实现访问控制和保护。 | 页面级别的保护,但通常不如分段灵活。 |
缺点 | 实现复杂,可能导致内存碎片。 | 可能导致内存碎片,但通常较少。 |
应用场景 | 适合需要逻辑分段的应用程序,如操作系统内核、数据库管理系统等。 | 适合大多数应用程序,特别是需要虚拟内存支持的应用程序。 |
代表性系统 | Unix、早期的 Windows 操作系统。 | Linux、现代 Windows 操作系统。 |
什么是 Channel?
在计算机科学和软件开发中,“Channel”(通道)是一个广泛使用的术语,它在不同的上下文中可以有不同的含义。这里我们将讨论几种常见的“Channel”的定义及其用途:
1. 操作系统中的 Channel
在操作系统中,“Channel”通常指的是用于在进程之间进行通信的一种机制。它可以看作是一种高级的 IPC(Inter-Process Communication)机制,用于在进程之间传递数据。
特点:
- 通信媒介:Channel 作为进程间通信的媒介,可以实现数据的发送和接收。
- 同步:通常 Channel 机制会包含同步机制,确保数据的正确传递。
例子:
- 管道(Pipe):在 Unix/Linux 系统中,管道是一种典型的 Channel,用于连接两个进程,使一个进程的输出成为另一个进程的输入。
- 命名管道(Named Pipe/FIFO):与管道类似,但可以在不同的进程或用户之间共享,通过文件名来标识。
2. 并发编程中的 Channel
在并发编程中,Channel 是一种用于通信和同步的基本原语,特别是在函数式编程语言和并发模型(如 Go 语言的 goroutines)中。
特点:
- 数据传递:Channel 用于在并发执行的线程或协程之间传递数据。
- 同步机制:Channel 提供了一种同步方式,确保数据的有序传递和一致性。
- 阻塞行为:Channel 可以是阻塞的或非阻塞的,具体取决于是否有数据可以接收或发送。
例子:
- Go 语言的 Channel:Go 语言中的 Channel 是用于 goroutine 之间通信的基本机制,可以传递任意类型的数据。
- Haskell 的 TChan:Haskell 中的
TChan
是一种用于线程间通信的 Channel。
3. 网络通信中的 Channel
在网络通信中,“Channel”通常指的是一种逻辑上的连接或通信路径,用于传输数据。
特点:
- 逻辑连接:在网络层面上,Channel 可以指一条逻辑上的连接,如 TCP 连接。
- 数据传输:Channel 用于在网络节点之间传输数据包。
例子:
- TCP 连接:TCP 连接可以视为一种 Channel,用于在客户端和服务器之间建立稳定的双向通信路径。
- WebSocket:WebSocket 是一种全双工的通信协议,可以在客户端和服务器之间建立持久的 Channel。
4. 应用程序中的 Channel
在某些应用程序中,Channel 也可以指一种用于组织和管理数据流的方式。
特点:
- 数据组织:Channel 可以用于组织不同类型的数据流。
- 逻辑隔离:不同的 Channel 可以用于隔离不同类型的数据传输。
例子:
- 多媒体播放器中的音频/视频 Channel:在多媒体播放器中,音频和视频数据流可以被视为不同的 Channel。
- 消息队列中的 Topic:在消息队列系统(如 Apache Kafka)中,Topic 可以被视为一种 Channel,用于组织不同类型的消息。
- Buffer:用于缓存数据,提高 I/O 效率。
- Selector:用于监控多个文件描述符的状态,实现多路复用。
- Reactor:结合 Selector 和事件驱动的设计模式,用于处理并发 I/O 操作。
- Select、Poll、Epoll:三种不同的文件描述符监控机制,分别适用于不同场景。
什么是 Buffer?
Buffer
通常指用于临时存储数据的内存区域。在计算机科学中,Buffer 主要用于缓存数据,以便进行批量处理或提高数据传输效率。
作用:
- 数据缓存:临时存储数据,以减少 I/O 操作次数。
- 流量控制:在数据传输过程中,用于平滑数据流,防止数据丢失。
- 同步:在多线程或多进程环境中,Buffer 用于同步数据。
例子:
- 网络编程中的 Buffer:在网络编程中,接收的数据通常先存储在一个 Buffer 中,然后再进行处理。
- 文件系统中的 Buffer:在文件系统中,读取或写入的数据通常先存储在 Buffer 中,以减少磁盘 I/O 操作。
什么是 Selector?
Selector
是一种用于监控多个文件描述符(File Descriptor)状态的技术,通常用于网络编程中的多路复用(Multiplexing)。
作用:
- 多路复用:同时监控多个文件描述符的状态,如读写就绪状态。
- 非阻塞:当没有数据可读或可写时,不会阻塞当前线程。
- 效率:相比于传统的阻塞 I/O,使用 Selector 可以大大提高 I/O 效率。
例子:
- Java NIO 中的 Selector:在 Java 的 NIO(New IO)框架中,
Selector
用于监控多个SocketChannel
的状态。 - POSIX 系统中的 Select 和 Poll:在 POSIX 系统中,
select()
和poll()
是常用的 Selector 实现。
什么是 Reactor?
Reactor
是一种设计模式,用于处理并发 I/O 操作。它结合了 Selector 和事件驱动的设计思想,通常用于构建高性能的网络服务器。
作用:
- 事件驱动:监听并处理多个 I/O 事件。
- 非阻塞:当没有 I/O 事件发生时,不会阻塞当前线程。
- 可扩展性:通过事件循环处理 I/O 事件,易于扩展和维护。
例子:
- Reactor 模式:在高性能服务器中,Reactor 模式常用于处理大量的并发连接。
- 事件驱动框架:如 libevent、libuv 等,提供了基于 Reactor 模式的设计框架。
Select、Poll、Epoll 之间有什么区别?
Select:select()
是一个用于监控多个文件描述符的系统调用。
- 支持的文件描述符数量有限(通常为 FD_SETSIZE)。
- 可以同时监控读、写和异常状态。
- 在 Linux 中,
select()
的效率较低,因为需要遍历所有的文件描述符。
适用场景:适合文件描述符较少的场景。
Poll:poll()
是 select()
的改进版本,同样用于监控多个文件描述符的状态。
- 不受文件描述符数量限制。
- 每个文件描述符的状态信息保存在
pollfd
结构中。 - 效率高于
select()
,因为不需要遍历所有文件描述符。
适用场景:适合文件描述符较多的场景。
Epoll:epoll()
是 Linux 内核提供的一个高效的文件描述符监控机制。
- 使用事件驱动的方式,只有状态改变的文件描述符才会被激活。
- 支持动态添加和删除监控对象。
- 效率最高,因为只关心状态发生变化的文件描述符。
适用场景:适合高性能网络服务器,尤其是需要处理大量并发连接的场景。
----------------计算机网络----------------
分层模型
OSI 七层模型
OSI 七层模型 是国际标准化组织提出的一个网络分层模型,其大体结构以及每一层提供的功能如下图所示:
TCP/IP 四层模型
TCP/IP 四层模型 是目前被广泛采用的一种模型,我们可以将 TCP / IP 模型看作是 OSI 七层模型的精简版本,由以下 4 层组成:
- 应用层
- 传输层
- 网络层
- 网络接口层
需要注意的是,我们并不能将 TCP/IP 四层模型 和 OSI 七层模型完全精确地匹配起来,不过可以简单将两者对应起来,如下图所示:
协议
常见网络协议汇总
1. 应用层有哪些常见的协议?
- HTTP(Hypertext Transfer Protocol,超文本传输协议):基于 TCP 协议,是一种用于传输超文本和多媒体内容的协议,主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我们使用浏览器浏览网页的时候,我们网页就是通过 HTTP 请求进行加载的。
- SMTP(Simple Mail Transfer Protocol,简单邮件发送协议):基于 TCP 协议,是一种用于发送电子邮件的协议。注意 :SMTP 协议只负责邮件的发送,而不是接收。要从邮件服务器接收邮件,需要使用 POP3 或 IMAP 协议。
- POP3/IMAP(邮件接收协议):基于 TCP 协议,两者都是负责邮件接收的协议。IMAP 协议是比 POP3 更新的协议,它在功能和性能上都更加强大。IMAP 支持邮件搜索、标记、分类、归档等高级功能,而且可以在多个设备之间同步邮件状态。几乎所有现代电子邮件客户端和服务器都支持 IMAP。
- FTP(File Transfer Protocol,文件传输协议) : 基于 TCP 协议,是一种用于在计算机之间传输文件的协议,可以屏蔽操作系统和文件存储方式。注意 ⚠️:FTP 是一种不安全的协议,因为它在传输过程中不会对数据进行加密。建议在传输敏感数据时使用更安全的协议,如 SFTP。
- Telnet(远程登陆协议):基于 TCP 协议,用于通过一个终端登陆到其他服务器。Telnet 协议的最大缺点之一是所有数据(包括用户名和密码)均以明文形式发送,这有潜在的安全风险。这就是为什么如今很少使用 Telnet,而是使用一种称为 SSH 的非常安全的网络传输协议的主要原因。
- SSH(Secure Shell Protocol,安全的网络传输协议):基于 TCP 协议,通过加密和认证机制实现安全的访问和文件传输等业务
- RTP(Real-time Transport Protocol,实时传输协议):通常基于 UDP 协议,但也支持 TCP 协议。它提供了端到端的实时传输数据的功能,但不包含资源预留存、不保证实时传输质量,这些功能由 WebRTC 实现。
- DNS(Domain Name System,域名管理系统): 基于 UDP 协议,用于解决域名和 IP 地址的映射问题。
2. 传输层有哪些常见的协议?
- TCP(Transmission Control Protocol,传输控制协议 ):提供 面向连接 的,可靠 的数据传输服务。
- UDP(User Datagram Protocol,用户数据协议):提供 无连接 的,尽最大努力 的数据传输服务(不保证数据传输的可靠性),简单高效。
3. 网络层有哪些常见的协议?
- IP(Internet Protocol,网际协议):TCP/IP 协议中最重要的协议之一,属于网络层的协议,主要作用是定义数据包的格式、对数据包进行路由和寻址,以便它们可以跨网络传播并到达正确的目的地。目前 IP 协议主要分为两种,一种是过去的 IPv4,另一种是较新的 IPv6,目前这两种协议都在使用,但后者已经被提议来取代前者。
- ARP(Address Resolution Protocol,地址解析协议):ARP 协议解决的是网络层地址和链路层地址之间的转换问题。因为一个 IP 数据报在物理上传输的过程中,总是需要知道下一跳(物理上的下一个目的地)该去往何处,但 IP 地址属于逻辑地址,而 MAC 地址才是物理地址,ARP 协议解决了 IP 地址转 MAC 地址的一些问题。
- ICMP(Internet Control Message Protocol,互联网控制报文协议):一种用于传输网络状态和错误消息的协议,常用于网络诊断和故障排除。例如,Ping 工具就使用了 ICMP 协议来测试网络连通性。
- NAT(Network Address Translation,网络地址转换协议):NAT 协议的应用场景如同它的名称——网络地址转换,应用于内部网到外部网的地址转换过程中。具体地说,在一个小的子网(局域网,LAN)内,各主机使用的是同一个 LAN 下的 IP 地址,但在该 LAN 以外,在广域网(WAN)中,需要一个统一的 IP 地址来标识该 LAN 在整个 Internet 上的位置。
- OSPF(Open Shortest Path First,开放式最短路径优先) ):一种内部网关协议(Interior Gateway Protocol,IGP),也是广泛使用的一种动态路由协议,基于链路状态算法,考虑了链路的带宽、延迟等因素来选择最佳路径。
- RIP(Routing Information Protocol,路由信息协议):一种内部网关协议(Interior Gateway Protocol,IGP),也是一种动态路由协议,基于距离向量算法,使用固定的跳数作为度量标准,选择跳数最少的路径作为最佳路径。
- BGP(Border Gateway Protocol,边界网关协议):一种用来在路由选择域之间交换网络层可达性信息(Network Layer Reachability Information,NLRI)的路由选择协议,具有高度的灵活性和可扩展性。
TCP 与 UDP 的区别
- 是否面向连接:UDP 在传送数据之前不需要先建立连接。而 TCP 提供面向连接的服务,在传送数据之前必须先建立连接,数据传送结束后要释放连接。
- 是否是可靠传输:远地主机在收到 UDP 报文后,不需要给出任何确认,并且不保证数据不丢失,不保证是否顺序到达。TCP 提供可靠的传输服务,TCP 在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制。通过 TCP 连接传输的数据,无差错、不丢失、不重复、并且按序到达。
- 是否有状态:这个和上面的“是否可靠传输”相对应。TCP 传输是有状态的,这个有状态说的是 TCP 会去记录自己发送消息的状态比如消息是否发送了、是否被接收了等等。为此 ,TCP 需要维持复杂的连接状态表。而 UDP 是无状态服务,简单来说就是不管发出去之后的事情了(这很渣男!)。
- 传输效率:由于使用 TCP 进行传输的时候多了连接、确认、重传等机制,所以 TCP 的传输效率要比 UDP 低很多。
- 传输形式:TCP 是面向字节流的,UDP 是面向报文的。
- 首部开销:TCP 首部开销(20 ~ 60 字节)比 UDP 首部开销(8 字节)要大。
- 是否提供广播或多播服务:TCP 只支持点对点通信,UDP 支持一对一、一对多、多对一、多对多;
- ……
我把上面总结的内容通过表格形式展示出来了!确定不点个赞嘛?
TCP | UDP | |
---|---|---|
是否面向连接 | 是 | 否 |
是否可靠 | 是 | 否 |
是否有状态 | 是 | 否 |
传输效率 | 较慢 | 较快 |
传输形式 | 字节流 | 数据报文段 |
首部开销 | 20 ~ 60 bytes | 8 bytes |
是否提供广播或多播服务 | 否 | 是 |
TCP 和 UDP 的选择
- UDP 一般用于即时通信,比如:语音、 视频、直播等等。这些场景对传输数据的准确性要求不是特别高,比如你看视频即使少个一两帧,实际给人的感觉区别也不大。
- TCP 用于对传输准确性要求特别高的场景,比如文件传输、发送和接收邮件、远程登录等等。
HTTP 和 HTTPS 的区别
- 端口号:HTTP 默认是 80,HTTPS 默认是 443。
- URL 前缀:HTTP 的 URL 前缀是
http://
,HTTPS 的 URL 前缀是https://
。 - 安全性和资源消耗:HTTP 协议运行在 TCP 之上,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议,SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。所以说,HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源。
- SEO(搜索引擎优化):搜索引擎通常会更青睐使用 HTTPS 协议的网站,因为 HTTPS 能够提供更高的安全性和用户隐私保护。使用 HTTPS 协议的网站在搜索结果中可能会被优先显示,从而对 SEO 产生影响。
URI 和 URL 的区别
- URI(Uniform Resource Identifier) 是统一资源标志符,可以唯一标识一个资源。
- URL(Uniform Resource Locator) 是统一资源定位符,可以提供该资源的路径。它是一种具体的 URI,即 URL 可以用来标识一个资源,而且还指明了如何 locate 这个资源。
URI 的作用像身份证号一样,URL 的作用更像家庭住址一样。URL 是一种具体的 URI,它不仅唯一标识资源,而且还提供了定位该资源的信息。
什么是 WebSocket?
WebSocket 是一种基于 TCP 连接的全双工通信协议,即客户端和服务器可以同时发送和接收数据。
WebSocket 协议在 2008 年诞生,2011 年成为国际标准,几乎所有主流较新版本的浏览器都支持该协议。不过,WebSocket 不只能在基于浏览器的应用程序中使用,很多编程语言、框架和服务器都提供了 WebSocket 支持。
WebSocket 协议本质上是应用层的协议,用于弥补 HTTP 协议在持久通信能力上的不足。客户端和服务器仅需一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
WebSocket 和 HTTP 的区别
WebSocket 和 HTTP 两者都是基于 TCP 的应用层协议,都可以在网络中传输数据。
下面是二者的主要区别:
- WebSocket 是一种双向实时通信协议,而 HTTP 是一种单向通信协议。并且,HTTP 协议下的通信只能由客户端发起,服务器无法主动通知客户端。
- WebSocket 使用 ws:// 或 wss://(使用 SSL/TLS 加密后的协议,类似于 HTTP 和 HTTPS 的关系) 作为协议前缀,HTTP 使用 http:// 或 https:// 作为协议前缀。
- WebSocket 可以支持扩展,用户可以扩展协议,实现部分自定义的子协议,如支持压缩、加密等。
- WebSocket 通信数据格式比较轻量,用于协议控制的数据包头部相对较小,网络开销小,而 HTTP 通信每次都要携带完整的头部,网络开销较大(HTTP/2.0 使用二进制帧进行数据传输,还支持头部压缩,减少了网络开销)。
TCP/IP 协议
常见的 HTTP 状态码
信息响应类(1xx):请求已被接受,需要客户端继续操作。
重定向类(3xx):需要客户端采取进一步的动作来完成请求。
成功类(2xx):请求已经被成功处理。
- 200 OK:请求已成功,返回请求的数据。
- 204 无内容:服务器成功处理了请求,但没有返回任何内容。
客户端错误类(4xx):请求包含语法错误或无法完成请求。
- 400 错误请求:服务器不能理解请求报文。
- 401 未授权:请求要求用户的身份认证。
- 403 禁止:服务器理解请求客户端的请求,但是拒绝执行此请求。
服务器错误类(5xx):服务器发生错误,无法完成请求。
- 500 内部服务器错误:服务器遇到未知错误。
- 501 未实现:服务器不支持请求的功能。
- 502 坏网关:作为网关或代理工作的服务器从上游服务器收到了无效响应。
- 503 服务不可用:服务器暂时过载或维护。
- 504 网关超时:作为网关或代理工作的服务器没有及时从上游服务器收到请求。
- 505 HTTP 版本不受支持:服务器不支持请求中所用的 HTTP 协议版本。
三次握手的过程
- SYN(同步序列编号,Synchronize):
- 客户端发送一个 SYN 包给服务器端,表示请求建立连接。这个包中包含了一个初始化的序号(Sequence Number),用于后续的数据传输。
- SYN-ACK(同步-确认,Synchronize-Acknowledge):
- 服务器端接收到 SYN 包之后,会发送一个 SYN-ACK 包作为应答。这个包中包含了一个自己的初始化序号,并且还包含了一个确认序号(Acknowledgment Number),这个确认序号是对客户端发出的 SYN 包的序号加一的确认。
- ACK(确认,Acknowledge):
- 客户端接收到服务器的 SYN-ACK 包后,会发送一个 ACK 包作为确认,这个包仅仅包含确认序号,确认序号是对服务器发出的 SYN-ACK 包的序号加一的确认。这样就完成了三次握手的过程,连接建立完成。
Client Server
| |
|-----> SYN (seq=x) | (第一次握手)
| |
| |<---- SYN,ACK (seq=y,ack=x+1) (第二次握手)
| |
|-----> ACK (seq=x+1,ack=y+1) | (第三次握手)
四次挥手的过程
- FIN(结束标志,Finish):
- 假设客户端想要关闭连接,它会发送一个 FIN 段到服务器,这个 FIN 段表明客户端已经没有更多的数据要发送了。该 FIN 段包含客户端的序列号 Seq = X。
- ACK(确认标志,Acknowledge):
- 服务器接收到客户端的 FIN 段后,会发送一个 ACK 段作为响应。这个 ACK 段确认了它已经收到了客户端的 FIN 段,并且确认了客户端的序列号 Seq = X + 1。此时,服务器可能仍然有未发送完的数据,所以这个 ACK 段可能还包含了一些待发送的数据。该 ACK 段包含服务器的序列号 Seq = Y 和确认号 Ack = X + 1。
- FIN(结束标志,Finish):
- 当服务器完成了所有数据的发送后,它也会发送一个 FIN 段到客户端,表明服务器也没有更多的数据要发送了。这个 FIN 段包含服务器的序列号 Seq = Z。
- ACK(确认标志,Acknowledge):
- 客户端接收到服务器的 FIN 段后,同样发送一个 ACK 段作为确认,表明它已经收到了服务器的 FIN 段,并且确认了服务器的序列号 Seq = Z + 1。此时,连接就可以正式关闭了。
Client Server
| |
|-----> FIN (seq=X) | (第一次挥手)
| |
| |<---- ACK (seq=Y, ack=X+1) (第二次挥手)
| |
| |----> FIN (seq=Z) | (第三次挥手)
| |
|-----> ACK (seq=X+1, ack=Z+1) | (第四次挥手)
断开连接
在标准的TCP/IP协议栈中,终止一个TCP连接主要是通过四次挥手来完成的。然而,在某些特殊情况下,还有其他的机制可以导致TCP连接的中断:
- RST(复位)包:发送一个带有RST标志的TCP段可以立即终止一个TCP连接。这种方式通常用于异常情况,如主机崩溃后重启或检测到恶意流量时。使用RST包断开会丢失未确认的数据,并且不会等待已发送的数据被接收。
- 超时:如果一段长时间内没有任何数据传输活动,TCP连接可能会因为超时而自动关闭。这种机制是为了防止死链的存在。
- 操作系统强制关闭:在某些情况下,操作系统可以直接关闭TCP连接,例如当系统检测到连接的一端已经不可达时。
粘包、拆包
粘包(Packet Clumping):指的是多个数据包在TCP层被合并成一个大的数据包进行发送,导致接收方无法区分这些数据包的边界。这通常发生在TCP的拥塞控制算法工作时,或者当发送方连续发送小的数据包而接收方在一个接收缓冲区中接收到的数据量超过了单个数据包的大小时。
发生原因:
- 发送方连续发送多个小的数据段,但接收方一次只收到了一个数据段。
- 这些数据段在TCP层被合并成了一个较大的数据段进行传输。
解决方案:
- 在发送数据时添加定长的包头。
- 使用特殊的分隔符来标识每个消息的边界。
- 使用固定长度的消息格式。
拆包(Packet Fragmentation):指的是一个较大的数据包在传输过程中被分割成几个更小的数据包进行发送,导致接收方接收到多个数据段,这些数据段原本属于同一个消息。
发生原因:
- 当一个数据包的大小超过了一定限制(如MTU,最大传输单元),路由器或网络设备可能会将其分割成几个较小的数据包进行传输。
- 接收方会收到这些被分割的数据包,并需要重组它们以恢复原始的消息。
解决方案:
- 通常情况下,TCP协议本身会处理这些被分割的数据包的重组,不需要应用层做额外的工作。
- 如果频繁出现拆包问题,可以考虑调整发送的数据包大小,使其不超过网络的最大传输单元(MTU)。
滑动窗口
主要作用:
- 流量控制:滑动窗口使得接收方可以控制发送方发送数据的速度,从而避免因发送速度过快而导致接收方无法及时处理数据。
- 提高带宽利用率:通过动态调整窗口大小,可以根据网络状况和接收方的能力最大化带宽的使用效率。
- 减少数据重传:通过有效的流量控制,减少因接收方缓冲区满而造成的丢包,从而减少不必要的数据重传。
- 改善延迟和吞吐量:滑动窗口机制有助于平衡延迟和吞吐量之间的关系,使得在网络条件变化时仍能保持较好的性能。
工作原理:
滑动窗口的核心思想是维护一个滑动的窗口范围,发送方和接收方通过TCP报文中的序号和确认号来协商这个窗口的大小和位置。
- 窗口大小:TCP头部中的“窗口大小”字段指明了接收方希望接收的数据量,即接收方缓冲区还能接受多少字节的数据。
- 序号和确认号:TCP报文中的序号用来标识数据的第一个字节的编号,而确认号则是指接收方期望接收的下一个字节的序号。
- 发送方的行为:发送方根据接收方提供的窗口大小发送数据,并且不能超出这个窗口的范围。一旦发送的数据达到了窗口的上限,发送方就需要等待接收方的确认或窗口更新后再继续发送。
- 接收方的行为:接收方接收到数据后,会根据接收到的数据量更新窗口大小,并通过ACK(确认)报文告诉发送方最新的窗口大小。
拥塞控制的步骤
TCP拥塞控制是为了防止过多的数据注入到网络中,从而引起网络拥塞的一种机制。TCP拥塞控制主要包括以下几个步骤或阶段:
1)慢启动(Slow Start)
慢启动阶段的目标是迅速增大拥塞窗口(Congestion Window, cwnd),同时避免过多地增加网络负载。在这个阶段,发送方会逐步增加发送的分组数量,直到达到某个阈值(ssthresh,slow start threshold)。
- 初始状态:当一个新的TCP连接建立时,或者网络中发生严重拥塞后重新开始传输时,cwnd通常被初始化为一个MSS(最大段大小)。
- 指数增长:每经过一个往返时间(Round Trip Time, RTT),cwnd就会翻倍。也就是说,发送方每次接收到一个ACK都会增加一个MSS的发送量。
2)拥塞避免(Congestion Avoidance)
当cwnd达到ssthresh时,进入拥塞避免阶段。这个阶段的目的是更加平缓地增加cwnd,以避免网络拥塞。
- 线性增长:每经过一个RTT,cwnd增加一个MSS的大小。也就是说,发送方每次接收到一个ACK时,并不会像慢启动那样翻倍增加,而是按部就班地增加。
- 目标:逐步增大cwnd,同时监控网络状况,避免拥塞。
3)快重传(Fast Retransmit)
快重传是一种加速重传丢失分组的机制。它允许发送方在没有等到重传计时器到期的情况下就重传丢失的数据。
- 触发条件:当发送方收到三个重复的ACK(意味着接收方已经接收到后面的分组,但中间的一个或几个分组丢失了),它就会立即重传丢失的分组,而不是等待计时器超时。
- 结果:这可以更快地恢复丢失的数据,减少传输延迟。
4)快恢复(Fast Recovery)
快恢复是在快重传之后的一个阶段,其目的是快速恢复到正常传输状态。
- 降低阈值:当快重传触发时,ssthresh会被减半(通常是设置为当前cwnd的一半),然后cwnd设置为ssthresh。
- 试探性增长:随后,发送方试探性地增大cwnd。每收到一个丢失分组的ACK,cwnd增加一个MSS。如果接收到足够多的ACK,则认为网络状况良好,可以回到拥塞避免阶段。
Token、Session、Cookie
都用于维护客户端和服务器之间用户认证和会话管理,其区别如下:
Cookie
优点 | 缺点 |
---|---|
简单易实现:存储在客户端(静态文件、数据库查询结果) | 安全风险:有被串改风险 |
本地缓存:读取速度快,不占用服务器存储 | 容量限制:4KB |
可用限制:用户可能禁用 |
Session
优点 | 缺点 |
---|---|
安全性高:存储在服务器端,不容易被恶意篡改和伪造 | 占用服务器资源 |
容量大:可以保存对象、大量的数据 | 扩展性差(分布式集群) |
依然需要依赖cookie跨域限制 |
Session怎么提高效率?
Session持久化:将session信息存储在持久化存储中,如数据库、文件系统或NoSQL存储中,这样可以避免将所有session信息存储在内存中,从而减少内存的使用量。
Session复制:将session信息从一台服务器复制到另一台服务器上,这样可以实现负载均衡,并将会话信息在多个服务器之间共享。
Session失效策略:设置合理的session失效策略,例如根据用户活动时间、最大不活动时间等来决定session的失效时间,可以减少无用的session信息。
集群:使用集群环境来分散请求和负载,这样可以使应用程序在多个服务器上运行,从而提高应用程序的性能和可扩展性。
总之,为了提高会话管理的效率,需要使用合理的持久化和集群技术,并设置合理的会话失效策略,以避免会话信息的无限增长。
Token
优点 | 缺点 |
---|---|
无状态性:服务器无需存储,提升可扩展性和性能 | 存储安全:客户端丢失或泄露Token可能导致安全问题 |
安全性:通过签名保证数据的完整性和来源的可靠性 | 传输负载:Token较多信息,会增加HTTP请求的大小 |
自包含性:Token自身包含用户信息和过期时间等,减少对服务器的查询 |
JWT Token
JWT 的组成
JWT 由三部分组成,每一部分由点号(.
)分隔:
- Header(头部)
- Payload(载荷)
- Signature(签名)
Header(头部):头部包含关于 JWT 的元数据,通常是一个 JSON 对象,编码为 Base64URL 字符串。头部包含的信息可能包括使用的签名算法(如 HMAC 使用 SHA-256 或 RSA 使用 SHA-256)以及令牌类型(通常是 "JWT")。示例:
{
"alg": "HS256",
"typ": "JWT"
}
Payload(载荷):载荷是存储 JWT 数据的地方。这也是一个 JSON 对象,编码为 Base64URL 字符串。载荷包含了一系列声明(Claims),声明可以是标准的也可以是自定义的。一些常用的声明包括 iss
(发行者)、exp
(过期时间)、sub
(主题)等。例如:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
Signature(签名):签名部分是用来验证 JWT 的发送方确实是谁他们声称是的人,并且确保载荷没有被篡改。为了创建签名,需要使用 Header 中指定的算法(如 HMAC 使用 SHA-256)对 Header 和 Payload 进行加密,并加上一个密钥(Secret)。密钥通常是只有发行者和接收者知道的秘密。接收方通过使用相同的密钥和算法解密签名,来验证令牌的真实性。示例签名:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JWT 的优点
- 无状态:JWT 是自包含的,因此不需要在服务器上保存会话状态,这使得 JWT 成为构建无状态、可扩展的应用程序的理想选择。
- 易于跨域使用:由于 JWT 可以通过 HTTP header 或者 POST 参数携带,所以非常适合跨域资源共享(CORS)。
- 轻量级:JWT 是紧凑的,可以减少网络传输的开销。
JWT 的局限性
- 过期管理:JWT 一旦签发,就不能撤销。如果令牌被盗或滥用,唯一的办法是让它过期或者在服务器端维护一个黑名单列表。
- 安全性依赖于密钥管理:JWT 的安全性依赖于密钥的安全性。如果密钥泄露,任何人都可以伪造 JWT。
JWT 的使用场景
JWT 通常用于身份验证和授权。在用户登录成功后,服务器会生成一个 JWT 并返回给客户端。客户端在后续的请求中将 JWT 放入 HTTP header(通常是 Authorization
头),这样服务器就可以验证用户的权限。
总的来说,JWT 是一种强大的工具,可以帮助开发者构建安全、高效的应用程序,特别是在微服务架构和分布式系统中。然而,使用 JWT 也需要谨慎处理安全性和过期管理等问题。
从输入 URL 到页面展示到底发生了什么?
总体来说分为以下几个步骤:
- 用户输入网址:在浏览器中输入指定网页的 URL。
- DNS 解析:浏览器通过 DNS 协议,获取域名对应的 IP 地址。
- 建立 TCP 连接:浏览器根据 IP 地址和端口号,向目标服务器发起一个 TCP 连接请求。
- 建立 SSL/TLS 加密连接:如果网站使用 HTTPS 协议,那么双方要交换密钥,建立会话密钥,使用密钥进行加密通信。
- 发送 HTTP 请求:浏览器在 TCP 连接上,向服务器发送一个 HTTP 请求报文,请求获取网页的内容。
- 服务器处理请求并响应:服务器收到 HTTP 请求报文后,处理请求,并返回 HTTP 响应报文给浏览器。
- 浏览器解析响应:浏览器收到 HTTP 响应报文后,解析响应体中的 HTML 代码,渲染网页的结构和样式,同时根据 HTML 中的其他资源的 URL(如图片、CSS、JS 等),再次发起 HTTP 请求,获取这些资源的内容,直到网页完全加载显示。
- 中断连接:浏览器在不需要和服务器通信时,可以主动关闭 TCP 连接,或者等待服务器的关闭请求。
HTTP 协议中 GET 和 POST 的区别
- GET:请求参数在 URL 中,用于获取数据。
- POST:请求参数在请求体中,用于修改数据。